from app import db, login_manager
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from datetime import datetime

# 定义权限常量
class Permission:
    VIEW = 0x01        # 查看权限 1
    COMMENT = 0x02     # 评论权限 2
    POST = 0x04        # 发帖权限 4
    MODERATE = 0x08    # 管理内容权限 8
    ADMIN = 0xff       # 管理员权限 255

# 用户角色关联表
user_roles = db.Table('user_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('role.id'))
)

class Role(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    description = db.Column(db.String(255))
    permissions = db.Column(db.Integer)
    users = db.relationship('User', secondary=user_roles, backref=db.backref('roles', lazy='dynamic'))

    def __init__(self, **kwargs):
        super(Role, self).__init__(**kwargs)
        if self.permissions is None:
            self.permissions = 0

    def has_permission(self, permission):
        return self.permissions & permission == permission

    def add_permission(self, permission):
        if not self.has_permission(permission):
            self.permissions += permission

    def remove_permission(self, permission):
        if self.has_permission(permission):
            self.permissions -= permission

    def reset_permissions(self):
        self.permissions = 0

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(120), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    last_login = db.Column(db.DateTime, nullable=True)
    is_active = db.Column(db.Boolean, default=True)
    session_token = db.Column(db.String(100), unique=True)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def has_permission(self, permission):
        for role in self.roles:
            if role.has_permission(permission):
                return True
        return False

    @property
    def is_admin(self):
        return self.has_permission(Permission.ADMIN)

    def can(self, permission):
        return self.has_permission(permission)

    def __repr__(self):
        return f'<User {self.username}>' 

    def update_last_login(self):
        self.last_login = datetime.utcnow()
        db.session.commit()

    @staticmethod
    def get_by_username(username):
        return User.query.filter_by(username=username).first()

    @staticmethod
    def get_by_email(email):
        return User.query.filter_by(email=email).first()

    def get_id(self):
        """重写 UserMixin 的 get_id 方法，返回包含会话令牌的标识"""
        return f"{self.id}:{self.session_token}"

    def generate_session_token(self):
        """生成新的会话令牌"""
        import secrets
        self.session_token = secrets.token_urlsafe(32)
        self.last_login = datetime.utcnow()

# 添加用户加载函数
@login_manager.user_loader
def load_user(id):
    try:
        # 分割用户ID和会话令牌
        user_id, session_token = id.split(':')
        user = User.query.get(int(user_id))
        # 验证会话令牌
        if user and user.session_token == session_token:
            return user
        return None
    except:
        return None

class Thesis(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    description = db.Column(db.Text, nullable=True)
    programming_language = db.Column(db.String(100), nullable=False)
    price = db.Column(db.Float, nullable=False)
    status = db.Column(db.String(20), default='pending')  # pending, accepted, completed
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship('User', backref=db.backref('theses', lazy=True))
    
    # 新增字段
    contact_info = db.Column(db.String(100), nullable=False)  # 联系方式
    deadline = db.Column(db.DateTime, nullable=False)  # 期望完成日期
    need_environment = db.Column(db.Boolean, default=False)  # 是否需要环境配置
    proposal_file = db.Column(db.String(255))  # 存储文件路径
    thesis_type = db.Column(db.String(20), nullable=False)  # design, thesis, full

    __table_args__ = (
        db.Index('idx_user_created', 'user_id', 'created_at'),
    )

    def __repr__(self):
        return f'<Thesis {self.title}>' 

class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    is_read = db.Column(db.Boolean, default=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    thesis_id = db.Column(db.Integer, db.ForeignKey('thesis.id'), nullable=False)
    
    user = db.relationship('User', backref=db.backref('messages', lazy=True))
    thesis = db.relationship('Thesis', backref=db.backref('messages', lazy=True)) 